package com.objcat.servicesecurity.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.objcat.servicesecurity.entity.po.PowerPo;
import com.objcat.servicesecurity.entity.po.RolePo;
import com.objcat.servicesecurity.entity.vo.RoleVo;
import com.objcat.servicesecurity.mapper.PowerMapper;
import com.objcat.servicesecurity.service.PowerService;
import com.objcat.servicesecurity.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;

/**
 * Created by wxb on 2018/10/26 0026.
 * 自定义的元数据源类，用来提供鉴权过程中，访问资源所需的角色
 *
 * 3.用户访问某资源/xxx时，FilterInvocationSecurityMetadataSource这个类的实现类
 * （MySecurityMetadataSource）会调用getAttributes方法来进行资源匹配。它会
 * 读取数据库resource表中的所有记录，对/xxx进行匹配。若匹配成功，则将/xxx对应所需的角色组成
 * 一个 Collection<ConfigAttribute>返回；匹配不成功则说明/xxx不需要什么额外的访问权限；
 */
@Slf4j
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Autowired
    private PowerService powerService;
    @Autowired
    private RoleService roleService;

    //本方法返回访问资源所需的角色集合
    AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        log.info("----进入MySecurityMetadataSource-----------------");
        //从object中得到需要访问的资源，即网址
        FilterInvocation filterInvocation = (FilterInvocation) object;
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        log.info("访问的uir地址为(包括参数)：{}",requestUrl);
//        log.info("无参数：{}",filterInvocation.getRequest().getServletPath());
        //从数据库中得到所有资源，以及对应的角色
        List<PowerPo> powerPoList = powerService.getAllPowers();
        for (PowerPo powerPo : powerPoList) {
            log.info("现在要进行power：{}-{}的role查询",powerPo.getPowerId(),powerPo.getPowerName());
            List<RoleVo> roleVoList = roleService.getRole(powerPo);
            //首先进行地址匹配
            log.info("roleVoList.size():{},",roleVoList.size());
            log.info("网址匹配：{},{},{}",powerPo.getUrl(),requestUrl,antPathMatcher.match(powerPo.getUrl(), requestUrl));
            if (antPathMatcher.match(powerPo.getUrl(), requestUrl)
                    && roleVoList.size() > 0) {
                //转变为String[]，方便执行createList
                String[] roles = new String[roleVoList.size()];
                for(int i=0; i<roleVoList.size(); i++){
                    roles[i]=roleVoList.get(i).getRoleName();
                }
                List list = SecurityConfig.createList(roles);
                log.info("角色Role的list.size:{}",list.size());
                log.info(list.toString());
                return SecurityConfig.createList(roles);
            }
        }
        log.info("匹配不成功，返回NONE");
        //匹配不成功返回一个特殊的ROLE_NONE
        return SecurityConfig.createList("ROLE_NONE");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
